In programming languages (especially functional programming languages) and type theory, an option type or maybe type is a polymorphic type that represents encapsulation of an optional value; e.g., it is used as the return type of functions which may or may not return a meaningful value when they are applied. It consists of a constructor which either is empty (often named None or Nothing), or which encapsulates the original data type A (often written Just A or Some A).
A distinct, but related concept outside of functional programming, which is popular in object-oriented programming, is called (often expressed as A?). The core difference between option types and nullable types is that option types support nesting (e.g. Maybe (Maybe String) ≠ Maybe String), while nullable types do not (e.g. String?? = String?).
In the Curry–Howard correspondence, option types are related to the absorption law for ∨: x∨1=1.
An option type can also be seen as a collection containing either one or zero elements.
The option type is also a Maybe monad where:
Nothing >>= f = Nothing -- Fails if the previous monad fails (Just x) >>= f = f x -- Succeeds when both monads succeed
The monadic nature of the option type is useful for efficiently tracking failure and errors.
-- Any constrained & non-limited type. type Element_Type is private;package Optional_Type is
-- When the discriminant, Has_Element, is true there is an element field, -- when it is false, there are no fields (hence the null keyword). type Optional (Has_Element : Boolean) is record case Has_Element is when False => Null; when True => Element : Element_Type; end case; end record;end Optional_Type;
Example usage:
package Optional_Integers is new Optional_Type (Element_Type => Integer); Foo : Optional_Integers.Optional := (Has_Element => True, Element => 5); Bar : Optional_Integers.Optional := (Has_Element => False);
| Some(a, true) of a | None(a, false)stadef option = option_t0ype_bool_type typedef Option(a: t@ype) = b:bool option(a, b)
fn show_value (opt: Option int): string =
case+ opt of | None() => "No value" | Some(s) => tostring_int s
implement main0 (): void = let
val full = Some 42 and empty = Nonein
println!("show_value full → ", show_value full); println!("show_value empty → ", show_value empty);end
constexpr std::optional
if (y != 0.0) { return x / y; }
return std::nullopt;}
void readDivisionResults(int x, int y) {
std::optional}result = divide(x, y); if (result) { std::println("The quotient of x: {} and y: {} is {}.", x, y, result.value()); } else { std::println("The quotient of x: {} and y: {} is undefined!"); }
int main(int argc, char* argv) {
readDivisionResults(1, 5); readDivisionResults(8, 0);}
Option.fold (fun _ x -> sprintf "The value is: %d" x) "No value"
let full = Some 42 let empty = None
showValue full |> printfn "showValue full -> %s" showValue empty |> printfn "showValue empty -> %s"
main :: IO () main = do
let full = Just 42 let empty = Nothing
putStrLn $ "showValue full -> " ++ showValue full putStrLn $ "showValue empty -> " ++ showValue empty
main : IO () main = do
let full = Just 42 let empty = Nothing
putStrLn $ "showValue full -> " ++ showValue full putStrLn $ "showValue empty -> " ++ showValue empty
public class OptionExample {
static String showValue(Optionalopt) { return opt.map(x -> String.format("The value is: %d", x)).orElse("No value"); }
public static void main(String[] args) { Optionalfull = Optional.of(42); Optional empty = Optional.empty();
System.out.printf("showValue(full): %s\n", showValue(full)); System.out.printf("showValue(empty): %s\n", showValue(empty)); }}
proc showValue(opt: Optionint): string =
opt.map(proc (x: int): string = "The value is: " & $x).get("No value")
let
full = some(42) empty = none(int)
echo "showValue(full) -> ", showValue(full) echo "showValue(empty) -> ", showValue(empty)
Option.fold ~none:"No value" ~some:(fun x -> "The value is: " ^ string_of_int x)
let () =
let full = Some 42 in let empty = None in
print_endline ("show_value full -> " ^ show_value full); print_endline ("show_value empty -> " ^ show_value empty)
opt.map_or("No value".to_owned(), |x| format!("The value is: {}", x))}
fn main() {
let full = Some(42); let empty = None;
println!("show_value(full) -> {}", show_value(full)); println!("show_value(empty) -> {}", show_value(empty));}
def showValue(opt: Option[Int]): String = opt.fold("No value")(x => s"The value is: $x")
def main(args: Array[String]): Unit = val full = Some(42) val empty = None
println(s"showValue(full) -> ${showValue(full)}") println(s"showValue(empty) -> ${showValue(empty)}")
return opt.map { "The value is: \($0)" } ?? "No value"}
let full = 42 let empty: Int? = nil
print("showValue(full) -> \(showValue(full))") print("showValue(empty) -> \(showValue(empty))")
Payload n can be captured in an if or while statement, such as , and an else clause is evaluated if it is null.
fn showValue(allocator: std.mem.Allocator, opt: ?i32) !u8 {
return if (opt) |n| std.fmt.allocPrint(allocator, "The value is: {}", .{n}) else allocator.dupe(u8, "No value");}
pub fn main() !void {
// Set up an allocator, and warn if we forget to free any memory. var gpa: std.heap.DebugAllocator(.{}) = .init; defer std.debug.assert(gpa.deinit() == .ok); const allocator = gpa.allocator();
// Prepare the standard output stream. const stdout = std.io.getStdOut().writer();
// Perform our example. const full = 42; const empty = null;
const full_msg = try showValue(allocator, full); defer allocator.free(full_msg); try stdout.print("showValue(allocator, full) -> {s}\n", .{full_msg});
const empty_msg = try showValue(allocator, empty); defer allocator.free(empty_msg); try stdout.print("showValue(allocator, empty) -> {s}\n", .{empty_msg});}
|
|